package cn.edu.scau.cmi.ema.service;

import cn.edu.scau.cmi.ema.base.CmiPagination;
import cn.edu.scau.cmi.ema.domain.Address;
import cn.edu.scau.cmi.ema.domain.Material;
import cn.edu.scau.cmi.ema.domain.Materialaddress;
import cn.edu.scau.cmi.ema.domain.Unit;
import cn.edu.scau.cmi.ema.service.base.CmiEmaService;
import cn.edu.scau.cmi.ema.util.CmiSqlUtil;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.*;
@Service("MaterialaddressService")
@Transactional

public class MaterialaddressServiceImpl extends CmiEmaService implements MaterialaddressService {
	public MaterialaddressServiceImpl() {
	}

	@Transactional
	public Materialaddress saveMaterialaddress(Materialaddress materialaddress) {

		if (materialaddress.getId() == null) {
			Address address = addressDAO.findAddressById(materialaddress.getAddress().getId());
			Material material = materialDAO.findMaterialById(materialaddress.getMaterial().getId());
			Unit unit = unitDAO.findUnitById(materialaddress.getUnit().getId());

			Materialaddress existingMaterialaddress = materialaddressDAO.findMaterialaddressByPhysicalPrimaryKey(
					material.getId(), address.getId(), materialaddress.getDate());

			materialaddress.setAddress(address);
			materialaddress.setMaterial(material);
			materialaddress.setUnit(unit);

			if (isEquals(materialaddress, existingMaterialaddress)) {
				return existingMaterialaddress;
			}

			materialaddress = materialaddressDAO.store(materialaddress);
			materialaddressDAO.flush();

		} else {
			Materialaddress existingMaterialaddress = materialaddressDAO
					.findMaterialaddressByPrimaryKey(materialaddress.getId());

			materialaddress = materialaddressDAO.store(materialaddress);
			materialaddressDAO.flush();
		}

		return materialaddress;
	}

	public void deleteMaterialaddress(Materialaddress materialaddress) {
		materialaddressDAO.remove(materialaddress);
		materialaddressDAO.flush();
	}

	@Transactional
	public void deleteMaterialaddresss(Set<Integer> deleteMaterialaddresssId) {
		Query query = materialaddressDAO.createNamedQuery("deleteMaterialaddresssById", -1, -1);
		query.setParameter(1, deleteMaterialaddresssId);
		query.executeUpdate();
	}

	@Transactional
	public Set<Materialaddress> loadMaterialaddresss() {
		return materialaddressDAO.findAllMaterialaddresss();

	}

	@Transactional
	public Set<Materialaddress> loadReferenceMaterialaddresss(Set<Materialaddress> materialaddresss) {
		Iterator<Materialaddress> materialaddresssIterator = materialaddresss.iterator();
		Set<Materialaddress> referencedMaterialaddresss = new HashSet<>();
		while (materialaddresssIterator.hasNext()) {
			Materialaddress currentMaterialaddress = materialaddresssIterator.next();

		}
		return referencedMaterialaddresss;
	}

	public Set<Materialaddress> loadMaterialaddresssByIdSet(Set<Integer> materialaddressIdSet) {

		Iterator<Integer> materialaddressIdIterator = materialaddressIdSet.iterator();
		Set<Materialaddress> materialaddressSet = new HashSet<>();
		while (materialaddressIdIterator.hasNext()) {
			Integer id = materialaddressIdIterator.next();
			Materialaddress currentMaterialaddress = materialaddressDAO.findMaterialaddressById(id);
			materialaddressSet.add(currentMaterialaddress);
		}
		return materialaddressSet;
	}

	@Transactional
	public List<Materialaddress> findAllMaterialaddresss(Integer startResult, Integer maxRows) {
		return new java.util.ArrayList<Materialaddress>(
				materialaddressDAO.findAllMaterialaddresss(startResult, maxRows));
	}

	@Transactional
	public Materialaddress findMaterialaddressByPrimaryKey(Integer id) {
		return materialaddressDAO.findMaterialaddressByPrimaryKey(id);
	}

	@Transactional
	public Integer countMaterialaddresss() {
		return ((Long) materialaddressDAO.createQuerySingleResult("select count(o) from Materialaddress o")
				.getSingleResult()).intValue();
	}

	@Transactional
	public Integer countMaterialaddresss(CmiPagination page) {
		String sql = CmiSqlUtil.createCountHql(page, Materialaddress.class);
		return ((Long) materialaddressDAO.createQuerySingleResult(sql).getSingleResult()).intValue();
	}

	/**
	 * search for name with ajax
	 *
	 */
	@Transactional
	public Integer countMaterialaddresssByName(String queryName) {
		Query query = materialaddressDAO.createNamedQuery("countMaterialaddresssByName", -1, -1);
		query.setParameter(1, queryName);
		return new Long((long) query.getSingleResult()).intValue();
	}

	@Transactional
	public Integer countMaterialaddresssByDetachedCriteria(CmiPagination page) {
		DetachedCriteria detachedCriteria = CmiSqlUtil.createDetachedCriteria(page, Materialaddress.class);
		Session session = (Session) entityManager.getDelegate();
		detachedCriteria.setProjection(Projections.rowCount());
		return new Long((long) detachedCriteria.getExecutableCriteria(session).uniqueResult()).intValue();
	}

	public Map<String, ?> loadMaterialaddressObjectReferencedSet(Materialaddress materialaddress) {
		HashMap<String, Object> objectReferencedSetMap = new HashMap<>();
		if (materialaddress.getAddress() != null) {

			Set<Integer> addressIds = new HashSet<Integer>();
			addressIds.add(materialaddress.getAddress().getId());
			objectReferencedSetMap.put("addressIds", addressIds);
		}
		if (materialaddress.getMaterial() != null) {

			Set<Integer> materialIds = new HashSet<Integer>();
			materialIds.add(materialaddress.getMaterial().getId());
			objectReferencedSetMap.put("materialIds", materialIds);
		}
		if (materialaddress.getUnit() != null) {

			Set<Integer> unitIds = new HashSet<Integer>();
			unitIds.add(materialaddress.getUnit().getId());
			objectReferencedSetMap.put("unitIds", unitIds);
		}

		return objectReferencedSetMap;
	}

	public Map<String, ?> loadMaterialaddressClassReferencedSet(Materialaddress materialaddress) {
		HashMap<String, Object> classReferencedSetMap = new HashMap<>();
		classReferencedSetMap.put("addresss", addressDAO.findAllAddresss());
		classReferencedSetMap.put("materials", materialDAO.findAllMaterials());
		classReferencedSetMap.put("units", unitDAO.findAllUnits());

		return classReferencedSetMap;
	}

	public boolean isEquals(Materialaddress materialaddress, Object obj) {
		if (obj == materialaddress)
			return true;
		if (!(obj instanceof Materialaddress))
			return false;
		Materialaddress comparedMaterialaddress = (Materialaddress) obj;
		if (!CheckPropertyEqual(materialaddress.getMaterial().getId(), comparedMaterialaddress.getMaterial().getId())) {
			return false;
		}
		if (!CheckPropertyEqual(materialaddress.getAddress().getId(), comparedMaterialaddress.getAddress().getId())) {
			return false;
		}
		if (!CheckPropertyEqual(materialaddress.getDate(), comparedMaterialaddress.getDate())) {
			return false;
		}
		return true;
	}

	public static <T> boolean CheckPropertyEqual(T originProperty, T comparedProperty) {
		// 基本类型经过参数传递后会自动装箱
		String[] className = originProperty.getClass().getName().split("\\.");
		if (className[0].equals("java") && className[1].equals("math")) {
			return ((Comparable) originProperty).compareTo(comparedProperty) == 0 ? true : false;
		} else {
			return originProperty.equals(comparedProperty);
		}
	}
}

